/******************************************************************************
 * Copyright (C)  2019  AnJuBao  All Rights Reserved.
 * 
 * spk_en.c
 * 
 * Created on: 2019-5-21 9:52:54
 *     Author: zqw  <qunwei.zhang@foxmail.com>
 *****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "spk_en.h"

#define GPIO0_BASE_ADDR      (0x20030000)  /* 获取方式 cat /proc/iomem */

#define GPIO_B5              (1*8 + 5)
#define SPK_EN_PIN           (GPIO_B5)

#ifndef PIN_OUT
#define PIN_OUT    (1)
#endif

#ifndef PIN_IN
#define PIN_IN     (!PIN_OUT)
#endif

typedef volatile unsigned int vuint; 


/*****************************************************************************
 * Function name  : spk_en
 * Description    : 在启动对讲或播放之后设置使能（注意：该函数是线程不安全的）
 * Param          :
 * Return  		  :
 * Created on     : 2019-5-21  9:53:04
 * Author         : zqw
 *****************************************************************************/
int spk_en(int opt)
{
    printf("--------------spk_en opt = %d\n", opt);
    int ret = -1;
    /* 系统调用获取页大小 (内存只能以页为单位进行映射) */
    int psize = getpagesize();
   
    /* 打开内存 */
    int fd = open("/dev/mem", O_RDWR);
    if(fd<0) {
        printf("--------------open /dev/mem fail!\n");
        return -1;
    }

    /* 将GPIO0的地址空间映射到虚拟内存 */
    vuint *gpio0_addr = (vuint *)mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO0_BASE_ADDR);
    if(gpio0_addr == NULL) {
        printf("--------------mmap gpio0_addr fail!\n");
        return -1;
    }

    /* 设置为输出 */
    vuint *ctl_reg = gpio0_addr + 1;
    *ctl_reg |= (1<<(SPK_EN_PIN%32));
    /* 设置为输入 */
    //*ctl_reg &= ~(1<<(SPK_EN_PIN%32)); 

    /* 设置高低电平 */
    vuint *dat_reg = gpio0_addr + 0;
    if(opt == SPK_DISABLE) {
        *dat_reg |= (1<<(SPK_EN_PIN%32));
    }else{
        *dat_reg &= ~(1<<(SPK_EN_PIN%32)); 
    }
    
    /* 同步 */
    msync((void *)gpio0_addr, psize, MS_ASYNC);

    /* 解除映射 */
    ret = munmap((void*)gpio0_addr, psize);

    close(fd);
    return ret;
}
